﻿/*Cat Lyons     CS4100      Spring 2011     Al Brouillette*/

using System;
using System.Collections.Generic;
using System.Text;

namespace Compiler_Phase_3
{
    public class Symbol               //Holds information required for a symbol
    {
        #region FIELDS

        string name;           //Name of symbol (if label, name = string label)
        int type;        //Type of symbol. 1 = label, 2 = identifier, 3 = const
        int value;                                      //Vaule of symbol (int)
        #endregion
//-----------------------------------------------------------------------------
        public Symbol(string n, int t, int v)                     //Constructor
        {
            name = n;        //initialize name. If string, name is string value
            type = t;                                          //intialize type
            value = v;                                       //initialize value
        }
        #region GET AND SET METHODS
          //Folowing methods return the value listed, or set var to value given
        public string Name                     //returns or sets name of symbol
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
        public int Type                        //returns or sets type of symbol
        {
            get
            {
                return type;
            }
            set
            {
                type = value;
            }
        }
        public int Value                           //returns or sets value(int)
        {
            get
            {
                return value;
            }
            set
            {
                this.value = value;
            }
        }
        #endregion
    }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
    public class SymbolTable
    {
        #region FIELDS

        Symbol[] symbolTable;       //Array of symbols to function as the table
        int currOpenIndex;                 //Index of first empty slot in array

        #endregion
//-----------------------------------------------------------------------------
        public SymbolTable()                                      //Constructor
        {
            symbolTable = new Symbol[1000];  //Create symbol table of size 1000
            currOpenIndex = 0;                //Set to the first index in array
        }
/*-----------------------------------------------------------------------------
         * AddSymbol: Checks if symbol is already in table. If it is, return  |
         * the index where it is located. If it is not, then add the symbol,  |
         * using the parameters to initialize a new symbol object, then add it|
         * to first open index in the table; increment the open index pointer.|
 *---------------------------------------------------------------------------*/
        public int AddSymbol(string symbol, int type, int value)
        {
            int symbolIndex;  //Holds index of given symbol, whether new or not
            int exists = LookupSymbol(symbol);      //If symbol exists in table
            if (exists == -1)       //If symbol does not exist in table, add it
            {
                if (symbol.Length > 30)
                {
                    symbol.Remove(30);   //Truncate anything over 30 characters
                    Console.WriteLine("\nError: Symbol more than 30 chars."
                        + "Truncating to 30 characters.\n");
                }
                Symbol temp = new Symbol(symbol, type, value);  //Create symbol
                symbolTable[currOpenIndex] = temp; //Insert at first open index
                symbolIndex = currOpenIndex;           //Save the current index
                currOpenIndex++;            //Increment to new first open index
            }
            else  //If symbol already exists, return the index it is located in
            {
                symbolIndex = exists;                          //Save the index
            }

            return symbolIndex;                      //return appropriate index
        }
/*-----------------------------------------------------------------------------
         * LookupSymbol: Iterates through symbolTable to find symbol given in |
         * parameters. If symbol exists in the table, it returns the int index|
         * where symbol is found. Otherwise, returns -1.                      |
 *---------------------------------------------------------------------------*/
        public int LookupSymbol(string symbol)
        {
            int symbolIndex = -1;  //Holds index of symbol if exists, -1 if not
            int tempIndex = 0;                             //Iteration variable
            bool stillLooking = true;    //false: symbol found or at null index
            while (stillLooking)          //indexes not empty, symbol not found
            {                        
                                     //Grab name of symbol in the current index
                if (symbolTable[tempIndex] != null)         //if index not null
                {
                    string tempName = symbolTable[tempIndex].Name;
                    if (tempName.CompareTo(symbol) == 0)//If symbol is the same
                    {
                        symbolIndex = tempIndex;//save index where symbol found
                        stillLooking = false;    //no longer looking for symbol
                    }
                    else if (tempIndex == 10) //reached end of table, not found
                    {
                        stillLooking = false;                    //stop looking
                    }
                }
                else                                  //If index is null (empty)
                {
                    stillLooking = false;                        //stop looking
                }
                tempIndex++;                    //increment to check next index
            }
            return symbolIndex;  //return index where found, or -1 if not found
        }
/*-----------------------------------------------------------------------------
         * GetSymbol: Finds the symbol at the given index of the symbol table |
         * and returns it. If index is null, returns an "error symbol" meant  |
         * for error checking without creating null-pointer exceptions        |
 *---------------------------------------------------------------------------*/
        public Symbol GetSymbol(int index)
        {
            if (symbolTable[index] == null)             //If no symbol in index
            {
                Symbol errSymbol = new Symbol("ErrSymbol", 0, 0); //void symbol
                Console.WriteLine("ERROR: Index points to null value. Error" +
                    "Symbol returned.");                   //Warn user of error
                return errSymbol;      //returns errorSymbol, indicates failure
            }
            else                                         //Index holds a symbol
            {
                return symbolTable[index];        //return symbol held in index
            }
        }
/*-----------------------------------------------------------------------------
         * PutSymbol: Goes to a given index and sets the type and value fields|
         * to values given. If no symbol at field, prints error message.      |
 *---------------------------------------------------------------------------*/
        public void PutSymbol(int index, int type, int value)
        {
            if (symbolTable[index] != null)         //if symbol at index exists
            {
                symbolTable[index].Type = type;       //change type to new type
                symbolTable[index].Value = value;   //change value to new value
            }
            else    //If symbol does not exist, print an error message for user
            {
                Console.WriteLine("ERROR: No symbol found at index.");
            }
        }
 /*-----------------------------------------------------------------------------
  * END OF FILE: SymbolTable.cs                                                |
  *---------------------------------------------------------------------------*/
    }
}
